package com.fengxu.gamescript.util

import android.content.Context
import android.net.Proxy
import android.os.Build
import android.text.InputType
import android.util.DisplayMetrics
import android.view.View
import android.widget.TextView
import com.fengxu.gamescript.R
import com.fengxu.gamescript.ui.base.BaseActivity
import com.xuexiang.xui.utils.DensityUtils
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import com.yhao.floatwindow.FloatWindow
import com.yhao.floatwindow.MoveType
import com.yhao.floatwindow.Screen
import okhttp3.*
import org.jetbrains.anko.doAsync
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.io.InputStream
import java.lang.Exception
import java.net.NetworkInterface
import java.net.URL
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import kotlin.experimental.xor

/**
 * 常用工具类
 */
object CommonUtils {

    init {
        System.loadLibrary("core")
    }

    /**
     * 判断是否采用了系统代理
     */
    fun isSystemProxy(ctx: Context): Boolean{
        val IS_ICS_OR_LATER: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH
        var proxyAddress: String?
        var proxyPort: Int?
        if(IS_ICS_OR_LATER){
            proxyAddress = System.getProperty("http.proxyHost")
            proxyPort = System.getProperty("http.proxyPort")?.toInt()
        } else {
            proxyAddress = Proxy.getHost(ctx)
            proxyPort = Proxy.getPort(ctx)
        }
        return !proxyAddress.isNullOrEmpty() && proxyPort != null
    }


    /**
     * 否开启了VPN
     */
    fun isVpn(): Boolean{
        for (networkInterface in NetworkInterface.getNetworkInterfaces()) {
            if(networkInterface.isUp && networkInterface.interfaceAddresses.size != 0){
                if(networkInterface.name == "tun0" || networkInterface.name == "ppp0"){
                    return true
                }
            }
        }
        return false
    }


    /**
     * 获取屏幕分辨率,无论是横屏还是竖屏，都返回竖屏的
     */
    fun getScreenMetric(): DisplayMetrics{
        val screenMetrics = DensityUtils.getScreenMetrics(true)
        val displayMetrics = screenMetrics
        val width = Math.min(screenMetrics.widthPixels, screenMetrics.heightPixels)
        val height = Math.max(screenMetrics.widthPixels, screenMetrics.heightPixels)
        displayMetrics.run {
            widthPixels = width
            heightPixels = height
        }
        return displayMetrics
    }

    /**
     * 从输入流中读取文档
     * @param stream 输入流
     */
    fun readInputStream(stream: InputStream):String{
        var bytes = stream.readBytes()
        return String(bytes)
    }

    /**
     * 获取md5加密
     */
    fun getMd5(str:String): String{
        return getMd5(str.toByteArray())
    }

    /**
     * 获取md5加密
     */
    fun getMd5(bytes: ByteArray): String{
        try {
            //获取md5加密对象
            val instance: MessageDigest = MessageDigest.getInstance("MD5")
            //对字符串加密，返回字节数组
            val digest:ByteArray = instance.digest(bytes)
            var sb : StringBuffer = StringBuffer()
            for (b in digest) {
                //获取低八位有效值
                var i :Int = b.toInt() and 0xff
                //将整数转化为16进制
                var hexString = Integer.toHexString(i)
                if (hexString.length < 2) {
                    //如果是一位的话，补0
                    hexString = "0" + hexString
                }
                sb.append(hexString)
            }
            return sb.toString()

        } catch (e: NoSuchAlgorithmException) {
            e.printStackTrace()
        }

        return ""
    }

    // 获取加载中对话框
    fun loadingDialog(
        context: Context,
        title: String = "提示",
        content: String = "加载中..."
    ): MaterialDialog {
        return MaterialDialog.Builder(context)
            .title(title)
            .content(content)
            .progress(true, 0)
            .progressIndeterminateStyle(false)
            .cancelable(false)
            .show()
    }

    // 获取普通弹出框
    fun toastDialog(
        context: Context,
        title: String = "提示",
        cancelable: Boolean = true,
        positiveText: String = "确定",
        onPositive: (() -> Unit)? = null,
        content: String
    ): MaterialDialog {
        return MaterialDialog.Builder(context)
            .title(title)
            .content(content)
            .cancelable(cancelable)
             .positiveText(positiveText)
             .onPositive { dialog, which ->  onPositive?.invoke()}
            .show()
    }

    // 弹出输入对话框
    fun inputDialog(
        context: Context,
        title: String = "提示",
        inputType: Int = InputType.TYPE_CLASS_TEXT,
        inputRange: IntRange? = null,
        positiveText: String = "确定",
        negativeText: String = "取消",
        onPositive: ((String) -> Unit)? = null,
        onNegative: ((String) -> Unit)? = null,
        cancelable: Boolean = false,
        fillInput: String = "",
        hint: String = "请输入",
        content: String
    ):MaterialDialog{
        return MaterialDialog.Builder(context)
            .title(title)
            .inputType(inputType)
            .input(hint, fillInput, false){ dialog, input-> onPositive?.invoke(input.toString())
            }
            .inputRange(inputRange?.start ?: 0, inputRange?.endInclusive ?: Int.MAX_VALUE)
            .content(content)
            .positiveText(positiveText)
            .negativeText(negativeText)
            .onNegative { dialog, which -> onNegative?.invoke(dialog.inputEditText!!.text.toString()) }
            .cancelable(cancelable)
            .show()
    }

    /**
     * 显示一个可在桌面显示的吐司
     * @param ctx 上下文对象
     * @param text 要显示的文字
     * @param time 显示时长，默认3秒
     */
    fun showDesktopToast(ctx: Context, text:String, time: Long = 3000L){
        FloatWindow.destroy("toast")
        val view = View.inflate(ctx, R.layout.flow_toast, null)
        (view.findViewById<View>(R.id.toast_customText) as TextView).setText(text)
        val screenMetrics = DensityUtils.getScreenMetrics(false)
        val viewWidth = (screenMetrics.widthPixels * 0.8).toInt()
        val x = (screenMetrics.widthPixels * 0.1).toInt()
        FloatWindow.with(ctx.applicationContext)
            .setWidth(viewWidth)
            .setX(x)
            .setY((DensityUtils.getScreenSize(false).y * 0.75).toInt())
            .setView(view)
            .setMoveType(MoveType.inactive)
            .setTag("toast")
            .setDesktopShow(true)
            .build()
        FloatWindow.get("toast").show()
        BaseActivity.uiHandler.postDelayed({
            FloatWindow.destroy("toast")
        },time)
    }

    /**
     * 异或加解密
     */
    fun xorEncrypt(source: ByteArray, key: String): ByteArray {
        val resArr: ByteArray = ByteArray(source.size)
        val keyArr = key.toByteArray()
        for (i in source.indices) {
            resArr[i] = source[i] xor keyArr[i % keyArr.size]
        }
        return resArr
    }

    /**
     * 获取apk的md5
     */
    fun apkMd5(ctx: Context):String{
        java.lang.String("aa").bytes
        val packageCodePath = ctx.packageCodePath
        return getMd5(FileInputStream(packageCodePath).readBytes()).toUpperCase()
    }

    /**
     * 判断指定的字符是不是base64字符
     */
    fun isBase64(str: String?): Boolean {
        if(str == null || str.isEmpty() || str.length % 4 != 0) return false
        for ((i, c) in str.toCharArray().withIndex()) {
            if(c.isLetterOrDigit() || c == '+' || c == '/') continue
            if(c == '=') {
                if (i + 1 < str.length && str[i + 1] != '=') {
                    return false
                }
                continue
            }
            return false
        }
        return true
    }


    /**
     * 下载文件到指定目录
     * @param url 资源文件地址
     * @param filepath  文件存储路径(包括文件名)
     */
    inline fun downloadFile(url:String, filepath:String, crossinline onResult:(Boolean)->Unit){
        var openConnection = URL(url).openConnection()
        openConnection.setRequestProperty("user-agent", "Mozilla/4.0")
        val file = File(filepath)
        doAsync {
            try {
                openConnection.connect()
                val inputStream = openConnection.getInputStream()
                val fos = file.outputStream()
                inputStream.copyTo(fos,4096)
                fos.close()
                onResult(true)
            }catch (e:Exception){
                if(file.exists()){
                    file.delete()
                }
                onResult(false)
            }
        }
    }


    /**
     * 核心解密脚本方法
     */
    external fun k(byteArray: ByteArray):ByteArray

    /**
     * 登录密码加密方法
     */
    external fun pEnc(str: String):String

    /**
     * 获取网站请求的根host
     */
    external fun getHost():String
}